package yun.web.springmvc.ext;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializeFilter;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import yun.web.springmvc.interceptor.InterceptorResult;
import yun.web.springmvc.paramcheck.ParamCheckResult;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MvcWriteUtil {

    static private FastJsonConfig fastJsonConfig = new FastJsonConfig();

    public static void write(HttpServletRequest req, HttpServletResponse resp, Object obj) {

        try {
            if (obj == null) return;

            // 写模板
            if (obj instanceof String) {
                String vp = (String) obj;
                new View().setVp(vp).write(req, resp);
                return;
            }

            // view
            if (obj instanceof View) {
                View v = (View) obj;
                //  写cookie
                v.writeCookies(resp);
                // 写响应头
                v.writeHeaders(resp);
                // 写模板
                String vp = v.vp;
                if (vp != null) {
                    v.write(req, resp);
                    // 直接返回
                    return;
                }

                if (v.odata != null) {
                    if (v.odata instanceof String) {
                        // odata为string类型 直接写字符串
                        ServletOutputStream os = resp.getOutputStream();
                        os.write(((String) v.odata).getBytes());
                        os.flush();
                        os.close();
                    } else {
                        writeJSON(resp, v.odata);
                    }
                    return;
                }

                if (v.data != null) {
                    writeJSON(resp, v.data);
                    return;
                }

                if (v.downloadFile != null) {
                    v.writeDownloadFile(resp);
                    return;
                }

                if (v.downloadInputStream != null) {
                    v.writeDownLoadStream(resp);
                    return;
                }

                if (v.previewFile != null) {
                    v.writePreviewFile(resp);
                    return;
                }

                if (v.previewInputStream != null) {
                    v.writePreviewStream(resp);
                    return;
                }

                if (v.qrCodeURL != null) {
                    v.writeQrCode(resp);
                    return;
                }

            }
/*
            if (obj instanceof DownLoadFile) {
                DownLoadFile downLoadFile = (DownLoadFile) obj;
                String disposition = StrUtil.format("attachment;filename={}", URLUtil.encode(downLoadFile.downloadname, downLoadFile.charset));
                resp.setHeader("Content-Disposition", disposition);
                resp.setHeader("Content-Type", "application/octet-stream");
                FileUtil.writeToStream(downLoadFile.file, resp.getOutputStream());
            } else if (obj instanceof PreviewFile) {
                PreviewFile previewFile = (PreviewFile) obj;
                //String disposition = StrUtil.format("filename={}", URLUtil.encode(downLoadFile.filename, downLoadFile.charset));
                //resp.setHeader("Content-Disposition", disposition);
                //resp.setHeader("Content-Type", previewFile.contentType);
                resp.setContentType(previewFile.contentType);
                FileUtil.writeToStream(previewFile.file, resp.getOutputStream());
            }
            */

            // 参数校验没通过
            if (obj instanceof ParamCheckResult) {
                write(req, resp, ((ParamCheckResult) obj).getR());
            }
            // 拦截器没通过
            else if (obj instanceof InterceptorResult) {
                InterceptorResult ib = (InterceptorResult) obj;
                // 转发
                if (ib.forward != null) {
                    View view = View.view(ib.forward) // 路径
                            .set(((InterceptorResult) obj).r); // 来自拦截器的数据
                    view.write(req, resp);
                }
                // 重定向
                else if (ib.redirect != null) {
                    resp.sendRedirect(ib.redirect);
                }
                // 路径为null, write data
                else if (ib.r != null) {
                    write(req, resp, ((InterceptorResult) obj).getR());
                }

            }
            // 其他的 写json
            else {
                writeJSON(resp, obj);
            }
        } catch (IOException e) {
            throw new MvcWriteException(e);
        }

    }

    private static void writeJSON(HttpServletResponse resp, Object obj) throws IOException {
        ByteArrayOutputStream bo = new ByteArrayOutputStream();

        //获取全局配置的filter
        SerializeFilter[] globalFilters = fastJsonConfig.getSerializeFilters();
        List<SerializeFilter> allFilters = new ArrayList<SerializeFilter>(Arrays.asList(globalFilters));


        int len = JSON.writeJSONString(bo, //
                fastJsonConfig.getCharset(), //
                obj, //
                fastJsonConfig.getSerializeConfig(), //
                //fastJsonConfig.getSerializeFilters(), //
                allFilters.toArray(new SerializeFilter[allFilters.size()]),
                fastJsonConfig.getDateFormat(), //
                JSON.DEFAULT_GENERATE_FEATURE, //
                fastJsonConfig.getSerializerFeatures());


        resp.setContentType("application/json;charset=UTF-8");
        resp.setContentLength(len);


        bo.writeTo(resp.getOutputStream());
        bo.flush();
        bo.close();
    }

    public static void writeStatic(HttpServletRequest req, HttpServletResponse resp, File file) throws MvcWriteException {
        /*String contentType = URLConnection.getFileNameMap().getContentTypeFor(file.getName());
        PreviewFile previewFile = new PreviewFile(file);
        previewFile.contentType = contentType;*/
        write(req, resp, View.build().preview(file, file.getName()));
    }


}
